package cn.wolfcode.shop.cloud.service.impl;


import cn.wolfcode.shop.cloud.BusinessException;
import cn.wolfcode.shop.cloud.Result;
import cn.wolfcode.shop.cloud.domain.Good;
import cn.wolfcode.shop.cloud.domain.SeckillGood;
import cn.wolfcode.shop.cloud.feign.GoodsFeignApi;
import cn.wolfcode.shop.cloud.key.KeyPrefix;
import cn.wolfcode.shop.cloud.mapper.SeckillGoodMapper;
import cn.wolfcode.shop.cloud.msg.SeckillGoodsCodeMsg;
import cn.wolfcode.shop.cloud.service.ISeckillGoodService;
import cn.wolfcode.shop.cloud.service.RedisService;
import cn.wolfcode.shop.cloud.util.SeckillKeyPrefix;
import cn.wolfcode.shop.cloud.vo.SeckillGoodVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;


@Service
public class SeckillServiceImpl implements ISeckillGoodService {

    @Autowired
    private SeckillGoodMapper seckillGoodMapper;

    @Autowired
    private GoodsFeignApi goodsFeignApi;



    @Autowired
    private RedisService redisService;

    @Override
    public List<SeckillGoodVO> query() {
        //1 查询出来秒伤商品列表所有的数据 List<SeckillGood>
        List<SeckillGood> seckillGoods = seckillGoodMapper.list();
        //2 把商品id放在一个set集合中
        Set<Long> goodIds = new HashSet<>();
        for (SeckillGood seckillGood : seckillGoods) {
            goodIds.add(seckillGood.getGoodId());
        }
        //需要把商品id的set集合转换成list集合,因为调用商品服务需要遍历集合id
        //3 根据id集合远程调用商品服务区查询数据
        //List<Good> goods = null;
        Result<List<Good>> result = goodsFeignApi.queryByIds(goodIds);

        if(result == null || result.getCode()!=200){
            throw new BusinessException(SeckillGoodsCodeMsg.PRODUCT_OPT);
        }
        //4 在内存中进行聚合操作
        Map<Long,Good>  data = new HashMap<>();
        for (Good good : result.getData()){
            data.put(good.getId(),good);
        }
        //5 返回list<vo>
        List<SeckillGoodVO> vos = new ArrayList<>();
        for (SeckillGood seckillGood :seckillGoods){
             SeckillGoodVO vo = new SeckillGoodVO();
             Good good = data.get(seckillGood.getGoodId());
            BeanUtils.copyProperties(good,vo);
            BeanUtils.copyProperties(seckillGood,vo);
            vos.add(vo);
        }
        //return common(seckillGoods);
        return vos;
    }
    public List<SeckillGoodVO> common(List<SeckillGood> seckillGoods){
        //存放商品id的信息
        Set<Long> goodIds = new HashSet<>();
        //2 获取到商品列表中的 商品id 并添加到一个集合
        for (SeckillGood seckillGood : seckillGoods) {
            goodIds.add(seckillGood.getGoodId());
        }

        //3 通过远程 调用去拿到商品集合信息
        Result<List<Good>> result = goodsFeignApi.queryByIds(goodIds);


        if(result == null || result.getCode()!=200){
            throw new BusinessException(SeckillGoodsCodeMsg.PRODUCT_OPT);
        }
       /* List<Good> goods = result.getData();
        //商品id 和 商品映射关系
        HashMap<Long,Good> map = new HashMap<>();
        for (Good good : goods) {
            map.put(good.getId(),good);
        }*/
        Map<Long,Good>  data = new HashMap<>();
        for (Good good : result.getData()){
            data.put(good.getId(),good);
        }

        //4 在内存中进行聚合操作
       /* List<SeckillGoodVO> goodVOS = new ArrayList<>();
        for (SeckillGood seckillGood : seckillGoods) {
            SeckillGoodVO seckillGoodVO =  new SeckillGoodVO();

            Long goodId = seckillGood.getGoodId();
            Good good = map.get(goodId);
            seckillGoodVO.setGoodDetail(good.getGoodDetail());
            seckillGoodVO.setGoodImg(good.getGoodImg());
            seckillGoodVO.setGoodName(good.getGoodName());
            seckillGoodVO.setGoodPrice(good.getGoodPrice());
            seckillGoodVO.setGoodStock(good.getGoodStock());
            seckillGoodVO.setGoodTitle(good.getGoodTitle());
            seckillGoodVO.setEndDate(seckillGood.getEndDate());
            seckillGoodVO.setGoodId(goodId);
            seckillGoodVO.setId(seckillGood.getId());
            seckillGoodVO.setSeckillPrice(seckillGood.getSeckillPrice());
            seckillGoodVO.setStockCount(seckillGood.getStockCount());
            seckillGoodVO.setStartDate(seckillGood.getStartDate());
            goodVOS.add(seckillGoodVO);
        }
        return goodVOS;*/
        List<SeckillGoodVO> vos = new ArrayList<>();
        for (SeckillGood seckillGood :seckillGoods){
            SeckillGoodVO vo = new SeckillGoodVO();
            Good good = data.get(seckillGood.getGoodId());
            BeanUtils.copyProperties(good,vo);
            BeanUtils.copyProperties(seckillGood,vo);
            vos.add(vo);
        }
        //return common(seckillGoods);
        return vos;
    }

    @Override
    public int decrCount(Long seckillId) {
        return seckillGoodMapper.decrCount(seckillId);
    }

    @Override
    public SeckillGoodVO find(Long seckillId) {
        SeckillGood seckillGood = seckillGoodMapper.get(seckillId);
        List<SeckillGood> list = new ArrayList<>();
        list.add(seckillGood);

        List<SeckillGoodVO> vos = common(list);
        return vos.get(0);
    }

    @Override
    public SeckillGoodVO findByCache(Long seckillId) {
        SeckillGoodVO sekillvo = redisService.hget(SeckillKeyPrefix.SECKILL_GOOD, "", seckillId + "", SeckillGoodVO.class);
        //从redis中取库存
        Integer count = redisService.get(SeckillKeyPrefix.SECKILL_STOCK, "" + seckillId, Integer.class);
        if(count < 0){
            count = 0;
        }
        sekillvo.setStockCount(count);
        return sekillvo;
    }

    @Override
    public List<SeckillGoodVO> queryByCache() {
        Map<String, SeckillGoodVO> resultMap = redisService.hgetAll(SeckillKeyPrefix.SECKILL_GOOD, "", SeckillGoodVO.class);

        Collection<SeckillGoodVO> values = resultMap.values();

        ArrayList<SeckillGoodVO> list = new ArrayList<>();

        //ArrayList<SeckillGoodVO> seckillGoodVOS= new ArrayList<>(resultMap.values());

        for (SeckillGoodVO seckillGoodVO : values) {
            Integer count = redisService.get(SeckillKeyPrefix.SECKILL_STOCK, "" + seckillGoodVO.getId(), Integer.class);
            if(count<0){
                count = 0;
            }
            seckillGoodVO.setStockCount(count);

            list.add(seckillGoodVO);
        }
        return list;
    }

    //回补预库存
    @Override
    public void incrStock(Long goodId) {
        seckillGoodMapper.incrStock(goodId);
    }

    //回补真实库存
    @Override
    public void syncStock(Long goodId) {
        SeckillGoodVO seckillGoodVO = find(goodId);

        redisService.set(SeckillKeyPrefix.SECKILL_STOCK,seckillGoodVO.getId()+"",seckillGoodVO.getStockCount());
        //把秒杀商品也放入到redis当中
        redisService.hset(SeckillKeyPrefix.SECKILL_GOOD,"",seckillGoodVO.getId()+"",seckillGoodVO);
    }


    /*
    @Override
    public SeckillGoodVO find(Long seckillId) {
        SeckillGood seckillGood = seckillGoodMapper.get(seckillId);
        List<SeckillGood> list = new ArrayList<>();
        list.add(seckillGood);

        List<SeckillGoodVO> vos = common(list);
        return vos.get(0);
    }

    @Override
    public int decrCount(Long seckillId) {
        return seckillGoodMapper.decrCount(seckillId);
    }


    @Override
    public SeckillGoodVO findByCache(Long seckillId) {
        SeckillGoodVO sekillvo = redisService.hget(SeckillKeyPrefix.SECKILL_GOOD, "", seckillId + "", SeckillGoodVO.class);
        Integer count = redisService.get(SeckillKeyPrefix.SECKILL_STOCK, "" + seckillId, Integer.class);
        if(count<0){
            count = 0;
        }
        sekillvo.setStockCount(count);
        return sekillvo;
    }

    @Override
    public List<SeckillGoodVO> queryByCache() {
        Map<String, SeckillGoodVO> resultMap = redisService.hgetAll((KeyPrefix) SeckillKeyPrefix.SECKILL_GOOD, "", SeckillGoodVO.class);

        Collection<SeckillGoodVO> values = resultMap.values();

        ArrayList<SeckillGoodVO> list = new ArrayList<>();

        for (SeckillGoodVO seckillGoodVO : values) {
            Integer count = redisService.get(SeckillKeyPrefix.SECKILL_STOCK, "" + seckillGoodVO.getGoodId(), Integer.class);
            if(count<0){
                count = 0;
            }
            seckillGoodVO.setStockCount(count);

            list.add(seckillGoodVO);
        }
        return list;
    }

    @Override
    public void incrStock(Long goodId) {
        seckillGoodMapper.incrStock(goodId);
    }

    @Override
    public void syncStock(Long goodId) {
        SeckillGoodVO seckillGoodVO = find(goodId);

        redisService.set(SeckillKeyPrefix.SECKILL_STOCK,seckillGoodVO.getId()+"",seckillGoodVO.getStockCount());
        //把秒杀商品也放入到redis当中
        redisService.hset(SeckillKeyPrefix.SECKILL_GOOD,"",seckillGoodVO.getId()+"",seckillGoodVO);
    }

    @Override
    public List<SeckillGoodVO> query() {
        //1 查询出来秒伤商品列表所有的数据
        List<SeckillGood> seckillGoods = seckillGoodMapper.list();
        return common(seckillGoods);
    }

    public List<SeckillGoodVO> common(List<SeckillGood> seckillGoods){
        //存放商品id的信息
        Set<Long> goodIds = new HashSet<>();
        //2 获取到商品列表中的 商品id 并添加到一个集合
        for (SeckillGood seckillGood : seckillGoods) {
            goodIds.add(seckillGood.getGoodId());
        }

        //3 通过远程 调用去拿到商品集合信息
        Result<List<Good>> result = goodsFeignApi.queryByIds(goodIds);

        if(result == null && result.getCode()!=200){
            throw new BusinessException(SeckillGoodsCodeMsg.PRODUCT_OPT);
        }
        List<Good> goods = result.getData();
        //商品id 和 商品映射关系
        HashMap<Long,Good> map = new HashMap<>();
        for (Good good : goods) {
            map.put(good.getId(),good);
        }

        //4 在内存中进行聚合操作
        List<SeckillGoodVO> goodVOS = new ArrayList<>();
        for (SeckillGood seckillGood : seckillGoods) {
            SeckillGoodVO seckillGoodVO =  new SeckillGoodVO();

            Long goodId = seckillGood.getGoodId();
            Good good = map.get(goodId);
            seckillGoodVO.setGoodDetail(good.getGoodDetail());
            seckillGoodVO.setGoodImg(good.getGoodImg());
            seckillGoodVO.setGoodName(good.getGoodName());
            seckillGoodVO.setGoodPrice(good.getGoodPrice());
            seckillGoodVO.setGoodStock(good.getGoodStock());
            seckillGoodVO.setGoodTitle(good.getGoodTitle());
            seckillGoodVO.setEndDate(seckillGood.getEndDate());
            seckillGoodVO.setGoodId(goodId);
            seckillGoodVO.setId(seckillGood.getId());
            seckillGoodVO.setSeckillPrice(seckillGood.getSeckillPrice());
            seckillGoodVO.setStockCount(seckillGood.getStockCount());
            seckillGoodVO.setStartDate(seckillGood.getStartDate());
            goodVOS.add(seckillGoodVO);
        }
        return goodVOS;
    }*/


}
